package com.sunni.service.Impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sunni.controller.AjaxRes;
import com.sunni.entity.Employee;
import com.sunni.entity.Menu;
import com.sunni.entity.PageListRes;
import com.sunni.entity.QueryVo;
import com.sunni.mapper.MenuMapper;
import com.sunni.service.MenuService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Iterator;
import java.util.List;

@Service
@Transactional
public class MenuServiceImpl implements MenuService {

    @Autowired
    private MenuMapper menuMapper;

    /*课时101-菜单管理 显示所有Menu (Menu表)*/
    @Override
    public PageListRes selectAllMenu(QueryVo queryVo) {
        PageListRes pageListRes = new PageListRes();

        /*设置PageBean*/
        Page<Object> page = PageHelper.startPage(queryVo.getPage(), queryVo.getRows());
        /*获取 所有Menu*/
        List<Menu> menuList = menuMapper.selectAll(queryVo);

        /*封装 PageListRes*/
        pageListRes.setTotal(page.getTotal());
        pageListRes.setRows(menuList);
        return pageListRes;
    }

    /*课时102-新增按钮,dialog form表单的 ‘父菜单’的下拉框-获取所有menu*/
    @Override
    public List<Menu> selectAllMenuNoPage() {
        return menuMapper.selectAll(null);
    }

    /*课时103-菜单管理页 添加按钮 insert进数据库menu表*/
    @Override
    public int addMenu(Menu menu) {
        return menuMapper.insert(menu);
    }

    /*课时105：菜单管理页，修改按钮，修改(Service层业务逻辑：不能选择子菜单做父菜单，那就判断我选择的父菜单的父菜单是不是我自己)*/
    @Override
    public AjaxRes updateMenu(Menu menu) {
        AjaxRes ajaxRes = new AjaxRes(false,"修改失败");


        /*我自己写的：
        查出父menu对象(比如，现在查到menu) -->
        父menu.getParent().getId();（系统管理没有父menu）（  （系统管理.getParent = null).getId：报空指针异常。  ）
        */
//        try {
//            Long parentMenuParentId = menuMapper.selectByPrimaryKey(menu.getParent().getId()).getParent().getId();
//            if (menu.getId() == parentMenuParentId){
//                ajaxRes.setSuccess(false);
//                ajaxRes.setMsg("修改失败, 不能选择子menu作为父menu！");
//                return ajaxRes;
//            }
//        } catch (NullPointerException e) {
//            System.out.println("当前menu的父menu为空，说明它是一级menu(不是任何人的子menu)。当前menu可以作为父menu。");
//            try {
//                menuMapper.updateByPrimaryKey(menu);
//                ajaxRes.setSuccess(true);
//                ajaxRes.setMsg("修改成功");
//                return ajaxRes;
//            } catch (Exception e1) {
//                System.out.println("e = "+e1);
//            }
//        }


        /*高新强写的：
        * 当前menu.getParent.getId, (修改页面 封装的。。.getParent.getId = 父menu下拉框，你选的那个父menu的id) -->
        * 根据这个(.getParent.getId)父menu的id，去查询父menu在数据库的parent_id（比如，系统管理parent_id 数据库为空，，那就返回null,,,直接和当前menu比较，，，，查到的父menu.id被查出来以后 不会再调用任何方法，所以不会报空指针异常。）
        * */
        /*获取父类的*/
        Long parenId = menu.getParent().getId();
        /*查询父menu的父menu的id*/
        Long grandfatherId = menuMapper.selectParentId(parenId); // 如果是一级menu，parent_id是null。因为一级menu没有父menu。
        /*不能选择子menu，当自己的父menu。*/
        if (menu.getId() == grandfatherId){
            ajaxRes.setMsg("修改失败, 不能选择子menu作为父menu！");
            return ajaxRes;
        }
        try {
            menuMapper.updateByPrimaryKey(menu);
            ajaxRes.setSuccess(true);
            ajaxRes.setMsg("修改成功 ");
            return ajaxRes;
        } catch (Exception e) {
            System.out.println("e = "+e);
        }

        return ajaxRes;
    }

    /*课时106：菜单管理页，删除按钮，删除menu.（业务逻辑，删除menu时判断，有没有子menu，有的话提示不能删除）*/
    @Override
    public AjaxRes deleteMenu(Long id) {
        AjaxRes ajaxRes = new AjaxRes(false,"删除失败");

        int sonMenuCount = menuMapper.selectSonMenuCount(id); //我的id,是谁的parent_id，我就是谁的爹，谁就是我儿子。
        if (sonMenuCount > 0){ // 如果 子menu数量大于0，说明我还有子menu，那我就不能删除。（我是一级menu，我下面有很多二级menu。把一级删了，二级咋办）
            ajaxRes.setSuccess(false);
            ajaxRes.setMsg("删除失败（当前menu，存在子menu。请先删除所有子menu）");
            return ajaxRes;
        }

        /*如果 count==0 说明没有子menu了，执行删除*/
        try {
            menuMapper.deleteByPrimaryKey(id);
            ajaxRes.setSuccess(true);
            ajaxRes.setMsg("删除成功");
        }catch (Exception e){
            System.out.println("e = " + e);
        }

        return ajaxRes;
    }


    /*课时107- 查询所有一级menu及其子menu*/
    @Override
    public List<Menu> selectTreeMenu() {
        // 课时108- menu表添加访问权限
        /* 课时108- 拿到全部menu，及其权限*/
        List<Menu> menuList = menuMapper.selectTreeMenu();

        /*课时109- 检查menu权限，移除员工无权访问的menu*/
        /*获取当前用户*/
        Employee employee = (Employee) SecurityUtils.getSubject().getPrincipal();
        /*判断是不是管理员，是:直接返回所有menu, 不是:检查他有哪些menu访问权限*/
        if (employee.getAdmin()==false){ //不是管理员
            /*menu做权限检验*/
            checkPermission(menuList);
        }

        return menuList;
    }

    /*课时109- 检查menu权限，移除员工无权访问的menu*/
    public void checkPermission(List<Menu> menuList){
        /*获取当前用户(主体)*/
        Subject subject = SecurityUtils.getSubject();
        /*遍历所有menu, 及其子menu (使用迭代器。因为要一遍遍历，一遍移除元素，所以只能使用迭代器。)*/
        Iterator<Menu> iterator = menuList.iterator();
        while (iterator.hasNext()){

            /*当前遍历到的这个menu*/
            Menu menu = iterator.next();

            /*判断这个menu的permission是不是空的，，不然 是空的 下面调用 获取权限相关方法会报空指针异常*/
            if (menu.getPermission() != null) { //有权限（不是空的权限）
                /*判断当前员工，有没有这个menu的需要的访问权限，如果该员工没有，就把没权限访问的menu从menu集合里移除！*/
                /*获取访问这个menu，所有需要的权限*/
                String menuPresource = menu.getPermission().getPresource();
                /*判断主体内(员工)，有没有这个权限*/
                if (subject.isPermitted(menuPresource) == false){ // 没有权限
                    /*移除这个menu*/
                    iterator.remove();
                    /*然后继续判断一下个menu*/
                    continue;
                }
            }

            /*判断这个menu, 是否存在子menu, 子menu也要做菜单权限检验*/
            if (menu.getChildren().size()>0){
                /*递归写法，继续检验子menu, 停止条件：没有子menu了。*/
                checkPermission(menu.getChildren());
            }
        }
    }

}
